<html>
<head>
<title>MVTools</title>
<link rel="stylesheet" type="text/css" href="../../avisynth.css">
<!--
Automatically generated, don't change:
$Id: mvtools095.htm,v 1.1 2005/10/03 16:31:31 macpaille Exp $
-->
</head>
<body>
<h1>MVTools</h1>
<h2>Abstract</h2>
<b>author:</b> Manao
<br><b>version:</b>     0.9.5
<br><b>download:</b>  <a href="http://jourdan.madism.org/~manao/">http:/
/jourdan.madism.org/~manao/</a><br>
<b>category:</b>  Misc Plugins<br>
<b>requirements:</b> YV12 Colorspace
<hr>
<h2>Table of contents
</h2>
<ul>
  <li><a href="#mvtools">
I) About MVTools</a>
  </li>
  <li><a href="#functions">II) Function descriptions</a></li>
  <li><a href="#examples">III) Examples</a></li>
  <li><a href="#disclaimer">IV) Disclaimer (don't skip that part, but I don't
force you to learn it either)</a></li>
  <li><a href="#revisions">V) Revisions</a></li>
</ul>
<h2><a name="MVTools"></a>I) About MVTools
</h2>
<p>Collection of filters (MVBlur, MVConvertFPS, MVDenoise, MVInterpolate, MVMask and
others) which uses motion vectors generated by this plugin.
</p>
<p>Note. There are <a href="mvtools.htm">more recent MVTools versions</a> with some new and improved functions,
but without motion interpolation functions (MVBlur, MVConvertFPS, MVInterpolate).</p>
<h2><a name="functions"></a>II) Function descriptions
</h2>
<h3>Common parameters
</h3>
<p>The filters which use motion vectors have common parameters. They allow for 
example to set the scene change detection thresholds. Moreover, filters may 
need one or two motion vectors stream. When two are needed, one is backward ( 
obtained by
<code>MVAnalyse</code>(isb = true) ), and the other is forward ( 
<code>MVAnalyse</code>(isb = false) ). By convention, the backward one has to 
be given first.
</p>
<p><var>mvsbw</var> : the backword motion vector
</p>
<p><var>mvsfw</var> : the forword motion vector
</p>
<p><var>int thSCD1</var> : threshold which decides whether a block has changed 
between the previous frame and the current one. When a block has changed, it 
means for me that motion estimation for him isn't relevant at all. It occurs 
for example at scene changes. So it is one of the thresholds used to tweak the 
scene changes detection engine. Default is 300. Raising it will lower the 
number of blocks detected as changed.
</p>
<p><var>int thSCD2</var> : threshold which sets how many blocks have to change 
for the frame to be considered as a scene change. It is ranged from 0 to 255, 0 
meaning 0 %, 255 meaning 100 %. Default is 130 ( which means 51 % ).
</p>
<h3>MVAnalyse
</h3>
<p><code>MVAnalyse</code> (<var>clip, int &quot;bw&quot;, int &quot;bh&quot;, int
&quot;pel&quot;, int &quot;lv&quot;, int &quot;fth&quot;, 
int &quot;sadt&quot;, int &quot;mpt&quot;,
int &quot;st&quot;, int &quot;stp&quot;, bool &quot;isb&quot;, int &quot;lambda&quot;</var>)
</p>
<p><var>bw, bh</var> : They are the width and the height of a block. Value
can only be 4 or 8. Larger blocks are less sensitive to noise, are faster, but
also less accurate. Defaults are 8 for both.
</p>
<p><var>pel</var> : it is the accuracy of the motion estimation. 1 means a
precision to the pixel. 2 means a precision to half a pixel, 4 to a quarter of
pixel and so on. Value can only be 1, 2, 4 or 8 ( beyond 8, it is useless and
waste a lot of memory ). Default : 1. For the moment, it's the only possible
value.
</p>
<p><var>lv</var> : it is the number of levels not used in the hierarchal
analysis made while searching for motion vectors. The lower the better. It is
kept variable for study's purposes only. Default : 0.
</p>
<p><var>fth</var> : Not used anymore, made useless by lambda.
</p>
<p><var>sadt</var> : Not used anymore, made useless by lambda and the speed
gain.
</p>
<p><var>st, stp</var> : <var>st</var> decides the type of search, and
<var>stp</var> is a setting for this search :</p>
<ul>
	<li><var>st </var>= 0 : 'OneTimeSearch'. <var>stp</var> is the step between
  each vectors tried ( if <var>stp</var> is superior to 1, step will be
  progressively refined ). It's the default search, with <var>stp </var>= 1.</li>
	<li><var>st </var>= 1 : 'NStepSearch'. N is set by <var>stp</var>. It's the
  most well known of the MV search algorithm.</li>
  <li><var>st </var>= 2 : Logarithmic search, also named Diamond Search.
  <var>stp</var> is the	initial step search, there again, it is refined
  progressively.</li>
  <li><var>st </var>= 3 : Exhaustive search, <var>stp</var> is the radius. It is
  slow, but it gives the best results, SADwise.</li>
</ul>
<p><var>isb</var> : allows to choose between a forward search ( between the
current frame and the previous one ) and a backward one ( between the current
frame and the following one ). <var>isb </var>= false means forward search.
</p>
<p><var>lambda</var> : set the coherence of the field of vectors. The higher,
the more coherent. However, if set too high, some 'true' motion vectors can be
missed. Default is 0, but values around 2000 are strongly recommended and will
be made defaults in the next release.
</p>
<h3>MVBlur
</h3>
<p><code>MVBlur</code> (<var>clip, clip mvsbw, clip mvsfw, int &quot;nb&quot;,
float &quot;rl&quot;, int &quot;fbw&quot;, string &quot;wf&quot;</var>)
</p>
<p>Allows to create a motion blur. The motion blur is created by interpolating
frames between the current frame and both next and previous frames, and then
make a weighted mean of these interpolations.
</p>
<p><var>nb</var> decides how many interpolations are made. The more, the better, and
the slower. <var>rl</var> is equivalent to the speed of a camera's shutter. The
higher, the stronger the motion blur. It's unit is in fps. <var>fbw</var> allows to
increase the size of the blocks that are moved along the motion vectors. For
example <var>fbw </var>= 2 will increase the block by a 2-pixels margin. This allows
less artifacting, but leads to a slightly less imprecise motion blur ( it will
be less directionnal ). Finally, <var>wf</var> controls the weighting of the
interpolations. Severals strings are possible here :
<ul>
  <li><var>wf </var>= "uniform" : Uniform weighting ( all the weights are equal
  to 1 ).</li>
  <li><var>wf </var>= "ramp" : the weight is proportionnal to the time between the
	interpolation and the current frame.</li>
	<li><var>wf </var>= "revramp" : it's the contrary.</li>
  <li><var>wf </var>= "hat" : it begins with a ramp, and finish like a revramp.</li>
  <li>else : it's a revramp.</li>
</ul>
<p>Defaults are : <var>nb </var>= 10, <var>rl </var>= 0.5, <var>fbw </var>= 2
and <var>wf </var>= "uniform".</p>
<h3>MVCompensate
</h3>
<p><code>MVCompensate</code> (<var>clip, clip vectors</var>)
</p>
<p>Do a full motion compensation of the frame. It means that the blocks pointed 
by MV in the previous frame ( or following, it depends on the setting of
<code>MVAnalyse</code> ) will be moved along the vectors to reach their places 
in the current frame.
</p>
<p>It differs from filters like MVinterpolate because here, the rebuilding is 
complete ( meaning by that that the blocks once moved aren't overlapping, and 
cover the whole picture ).
</p>
<p>For the moment, it doesn't move the chroma ( because it needs a spatial 
interpolation algorithm to do so
).
</p>
<h3>MVConvertFPS
</h3>
<p><code>MVConvertFPS</code> (<var>clip, clip mvbw, clip mvfw, int
&quot;nb&quot;, float &quot;rl&quot;, int &quot;fbw&quot;, int &quot;sbw&quot;, 
int
&quot;rbw&quot;, int &quot;bvt&quot; [, int num, int den], float
&quot;fps&quot;, string &quot;wf&quot;</var>)
</p>
<p>Will change the framerate of the clip, without changing its length. As with 
<code>MVBlur</code>,
<var> nb</var> is the number of frames built in order to create one interpolate 
frame.
<var> rl</var> camera's shutter speed and <var> wf</var> is the normalization 
function.
<var>fbw</var>, <var> sbw</var> and <var> rbw</var> allows to increase the size 
of the blocks moved.
<var> bvt</var> is a threshold which decides whether a motion vector is valid 
or not. The default value makes all vectors valid.
<var> num</var> and <var> den</var> are the numerator and the denominator of 
the new framerate. You can also give this number using the
<var> fps</var> parameters.
</p>
<p>Defaults are : <var>nb</var> = 1, <var>rl</var> = 0, <var>fbw</var> = 4, 
<var>sbw</var>
= 0, <var>rbw</var> = 0, <var>bvt</var> = 35000 and <var>wf</var> =
&quot;uniform&quot;.
</p>
<h3>MVDenoise
</h3>
<p><code>MVDenoise</code> (<var>clip, clip mvbw, clip mvfw, int 
&quot;thT&quot;, int
&quot;sadT&quot;</var>)
</p>
<p>Makes a basic temporal denoising with motion compensation. Both previous and 
following frames are motion compensated and then merged into the current frame. 
The two thresholds are used to prevent artifacts.
</p>
<p>The first one, <var>thT</var>, decides whether the pixel which comes from 
the previous or the following frame has to be taken into account. If this pixel 
differs more than
<var>thT</var> from the pixel of the current frame, it is not used.
</p>
<p>The second one, <var>sadT</var>, decides whether the block has changed or 
not ( same principle as
<var> thSCD1</var> ). If it has changed, the pixel aren't merged with those of 
the previous or following frame.
</p>
<p>Defaults are : <var>thT</var> = 10 and <var>sadT</var> = 160.
</p>
<p>
I would say ( without much testing ) that :
</p>
<ul>
  <li><var>thT</var> = 5-10, sadt = 100-200 : weak denoising</li>
  <li><var>thT</var> = 10-15, sadt = 200-300 : medium denoising</li>
  <li><var>thT</var> = 15-25, sadt = 300-500 : strong denoising</li>
</ul>
<h3>MVInterpolate
</h3>
<p><code>MVInterpolate</code> (<var>clip, clip mvbw, clip mvfw, int
&quot;nb&quot;, float &quot;bl&quot;, float &quot;el&quot;, int 
&quot;fbw&quot;, int
&quot;sbw&quot;, int &quot;rbw&quot;, int &quot;bvt&quot;, string 
&quot;wf&quot;</var>)
</p>
<p>Allows to shift temporally the video from a non integer number of frames, 
between 0.0 and 1.0. Works the same way
<code> MVBlur</code> and <code> MVConvertFPS</code> do, which means 
<var>nb</var>,
<var>fbw</var>, <var>sbw</var>, <var>rbw</var>, <var>bvt</var> and <var>wf</var>
work the same way. <var>bl</var> and <var>el</var> define the beginning and the 
end of the interpolation. If <var>bl</var>  is different from <var>el</var>, the created frame is 
slightly blured. The interpolation is made between the current frame and the 
previous one.
</p>
<p>Defaults are <var>nb</var> = 5, <var>bl</var> = 0.4, <var>el</var> = 0.6, 
<var>fbw</var>
= 4, <var>sbw</var> = 0, <var>rbw</var> = 0, <var>bvt</var> = 35000 and 
<var>wf</var>
= &quot;uniform&quot;.
</p>
<h3>MVMask
</h3>
<p><code>MVMask</code> (<var>clip, clip vectors, int &quot;ml&quot;, float
&quot;gamma&quot;, bool &quot;showsad&quot;, int &quot;Ysc&quot;</var>)
</p>
<p>Creates a motion mask from the motion vectors' length. It builds a better 
mask than
<a href="masktools.htm#motionmask"> MotionMask</a> ( <a href="masktools.htm"> 
MaskTools</a> ) because motion vectors are a lot more reliable than the 
algorithm of MotionMask.
</p>
<p>The mask is output only on the luma plane. 0 means no motion at all ( the 
length of the motion vector is null ), whereas 255 means maximum motion, and is 
defined by
<var>ml</var>. When the vector's length is superior or equal to ml, the output 
value is 255.
<var>gamma</var> is used to defined the relation length - value. 
<var>gamma</var>
= 1.0 implies a linear relation, whereas <var>gamma</var> = 2.0 gives a 
quadratic relation.
</p>
<p><var>showsad</var> allows to build a mask of the SAD values instead of the
vectors' length. And finally, <var>Ysc</var> is the value taken by the mask on scene change
<p>Defaults are : <var>ml</var> = 100, <var>gamma</var> = 1.0, <var>showsad</var> = false and
<var>Ysc</var> = 0.</p>
<h3>MVShow
</h3>
<p><code>MVShow</code> (<var>clip, clip vectors, int &quot;scale&quot;, int
&quot;sil&quot;, int &quot;tol', bool &quot;showsad&quot;</var>)
</p>
<p>Shows the motion vectors. <var>scale</var> allows to enlarge the motion
vectors, in order for example to gain in accuracy ( when
<var>pel</var> &gt; 1 and <var>scale</var> = 1, you can't see
a variation of less than one pixel ).
<var>sil</var> allows to see a different level of analysis ( when searching for 
motion vectors, a hierarchal analysis is done, and it may be interesting to see 
what happens at higher levels ).
<var>tol</var> is a tolerance threshold. If the distorsion induced by the 
motion vector is over tol the vector isn't shown.
Finally, <var>showsad</var> allows to show the mean SAD after compensating the
picture.</p>
<p>Defaults are : <var>scale</var> = 1, <var>sil</var> = 0, <var>tol</var> =
20000 and <var>showsad</var> = false ( which shows all vectors ).
</p>
<h2><a name="examples"></a>III) Examples
</h2>
<p>To show the motion vectors ( forward ) :
</p>
<pre>vectors = source.MVAnalyse(isb = false)
return source.MVShow(vectors)</pre>
<p>To show the backward one :
</p>
<pre>vectors = source.MVAnalyse(isb = true)
return source.MVShow(vectors)</pre>
<p>To use MVMask :
</p>
<pre>vectors = source.MVAnalyse(isb = false)
return source.MVMask(vectors)</pre>
<p>To use MVBlur :
</p>
<pre>vectorsfw = source.MVAnalyse(isb = false)
vectorsbw = source.MVAnalyse(isb = true)
return source.MVBlur(vectorsbw, vectorsfw)</pre>
<p>It's the same for <code>MVInterpolate</code>, <code> MVDenoise</code> and 
<code>MVConvertFPS</code>.
</p>
<p>To denoise :
</p>
<pre>backward_vectors = source.MVAnalyse(isb = true, lambda = 2000)
forward_vectors = source.MVAnalyse(isb = false, lambda = 2000)
return source.MVDenoise(backward_vectors, forward_vectors, tht = 10, sadt = 300)</pre>
<p>A very slow, but also very good motion blur:
</p>
<pre># Assuming 25fps material. Works very well for my CG material.
vec_back = source.MVAnalyse(lambda=2000, isb=true)
vec_forw = source.MVAnalyse(lambda=2000, isb=false)
MVConvertFPS(last, vec_back, vec_forw, fps=100, fbw=2, thSCD2=255, thSCD1=200)
TemporalSoften(2, 255, 255, 0, 2)
SelectEvery(4,0)</pre>
<p>Motion compensated 60i to 24p conversion:
</p>
<pre>function KernelBob(clip a, int &quot;ord&quot;)
{
  f = a.KernelDeint(order=ord)
  e = a.SeparateFields.Trim(1,0).Weave().KernelDeint(order=1-ord)
  Interleave(f,e)
}

function MVConvert60ito24p(clip x, int &quot;mode&quot;)
{
mode = default(mode, 2)
mbl = 0.1

vectorsforward = x.MVAnalyse(isb = false)
vectorsbackward = x.MVAnalyse(isb = true)

y = x.MVInterpolate(vectorsbackward, vectorsforward, nb = 4, bl = 0.5 - mbl, el = 0.5 + mbl, wf = &quot;hat&quot;)

Interleave(y, x)
mode0 = SelectEvery(5, 2)
mode1 = Overlay(SelectEvery(5,3),SelectEvery(5,2),opacity=0.5)
mode2 = Overlay(Overlay(SelectEvery(5,1),SelectEvery(5,3),opacity=0.5),SelectEve
ry(5,2),opacity=0.3)
mode3 = Overlay(Overlay(SelectEvery(5,0),SelectEvery(5,3),opacity=0.5),Overlay(S
electEvery(5,1),SelectEvery(5,2),opacity=0.5),opacity=0.5)

(mode==0) ? mode0 : (mode==1) ? mode1 : (mode==2) ? mode2 : mode3
}

x = source.KernelBob(ord=0)  # or any other bobber
MVConvert60ito24p(x)</pre>
<h2><a name="disclaimer"></a>IV) Disclaimer
</h2>
<p>This plugin is released under the GPL license. You must agree to the terms of
'Copying.txt' before using the plugin or its source code.
</p>
<h2><a name="revisions"></a>V) Revisions
</h2>
<p>0.9.5
</p>
<ul>
  <li>Huge rewritting of the core engine. Vectors are now searched with a
   precision up to the pixel ( because no other filters can use yet more
   precise vectors, except MVShow ). The search engine is now fast ( which
   doesn't mean necessarily that the filters which use it are fast )</li>
   <li>A new parameter for MVAnalyse : lambda. See the documentation of the
   filter to see how it works</li>
   <li>MVDenoise works better.</li>
</ul>
<p>0.9.4
</p>
<ul>
  <li>Vectors can be saved to a file. In order to do so, add the parameter 
filename="C:\foo.bar" to the filter MVAnalyse. If the file doesn't exist, 
vectors will be saved into it. If it exists, vectors will be read from it. But, 
be warned :
    <ul>
      <li>The file for a whole movie will be around 500 MB</li>
      <li>Saving / reading from a file need for the moment a linear access to 
the frames, so it has to be used only when encoding the movie, not when doing 
random access in it.</li>
      <li>The speed gain is not as great as one may hope, because SADs can't be 
saved ( it would take too much space ) and so have to be recomputed.</li>
    </ul>
  </li>
  <li>The filter MVDenoise now works on 5 frames, and its parameters are now 
"thT" and "sadT" ( have a look in the documentation to see how they work ). It 
works nice ( very good for heavy denoising )</li>
  <li>The scene change detection thresholds have slightly changed. Now, a block 
has changed if its SAD it over thSCD1. The default for thSCD1 is 300, and for 
thSCD2 it is 130. It orks well ( better than the previous SCD engine ).<br>
  </li>
</ul>
<p>0.9.3</p>
<ul>
  <li>Last cleanings in the search of the motion vectors. It should be slightly 
faster</li>
  <li>More search parameters can be set by the user, especially the search 
algorithm. See the documentation</li>
  <li>Server / client implemented. You now first have to use MVAnalyse, and 
then the filter you want. Look at the documentation and at the examples I'll 
give alter.</li>
  <li>MVCompensate is separated from MVShow ( it's more logic that way ). For 
the moment, it doesn't move the chroma ( same behavior as MVShow in the latest 
releases )</li>
  <li>Some cleaning in MVBlur / MVInterpolate / MVConvertFPS, but still some 
work to do. Now, MVBlur blurs around the frame, not between the frame and the 
previous one.</li>
  <li>Half of the work is done for writing vectors to a file. But the resulting 
file will be large ( around 500 MB - 1 GB I guess ).</li>
  <li>MVDenoise is slightly faster ( at least it should )</li>
  <li>Copies are optimized inside the filter, thanks to avisynth's copy 
functions.</li>
  <li>MVShow can display the mean SAD of the compensation ( using showsad = 
true )</li>
</ul>
<p>0.9.2.1</p>
<ul>
  <li>MVInterpolate makes its come back.</li>
  <li>MVConvertFPS should work on the last few frames of the clip</li>
</ul>
<p>0.9.2</p>
<ul>
  <li>MVInterpolate doesn't exist anymore.</li>
  <li>MVBlur and MVConvertFPS have been improved. They also have got new 
parameters, have a look at the documentation.</li>
  <li>MVShow gets back its compensate mode ( MVShow(cm = true) )</li>
</ul>
<p>$Date: 2005/10/03 16:31:31 $
</p>
</body>
</html>
